<template>
    <div>
        <a-button type='primary' @click='openAddCategory'>{{$c('add', 'category')}}</a-button>
    </div>
    <div class='m-t-20'>
        <BTable :columns='columns' :data='dataRows' row-key='id'>
            <template #$action='{record}'>
                <BTextButton @click='openItemAdd(record)'>{{$t('add')}}</BTextButton>
            </template>
        </BTable>
    </div>

    <BDialog v-model:visible='visible' :title='dialogTitle' width='600px' :confirm='submit'>
        <template v-if='action === "category"'>
            <BForm ref='formRef' :label-col='{span : 5}' :fields='formCategoryFields'></BForm>
        </template>
        <template v-else>
            <BForm ref='formRef' :label-col='{span : 5}' :fields='formItemFields'></BForm>
        </template>
    </BDialog>
</template>

<script lang='ts' setup>
    import { listApi, saveCategoryApi, saveItemApi, deleteCategoryApi, deleteItemApi } from "@/api/system/Dictionary";
    import { useI18nStore } from "@/store/i18n";
    import { generateCodeFromUid, recursionFn } from "@/utils";
    import { message, Modal } from "ant-design-vue";
    import { computed, ref } from "vue";

    const i18n = useI18nStore()

    const visible = ref(false)
    const formRef = ref()
    const dialogTitle = ref()
    const action = ref<'category'|'item'>()

    const categorys = ref<any[]>([])
    const items = ref<any[]>([])


    const columns = ref<Column[]>([
        {
            dataIndex : 'name',
            title : i18n.t('name'),
            translate : true,
        },

        {
            dataIndex : 'code',
            title : i18n.t('code'),
        },

        {
            dataIndex : '$action',
            title : i18n.t('operation'),
            align : 'center',
            $edit(row) {
                dialogTitle.value = i18n.t('edit')
                if(row.hasOwnProperty('categoryId')) {
                    action.value = 'item'
                    formItemFields.forEach(field => {
                        field.defaultValue = row[field.name]
                    })
                }else {
                    action.value = 'category'
                    formCategoryFields.forEach(field => {
                        field.defaultValue = row[field.name]
                    })
                    
                }

                visible.value = true
            },

            async $delete(row) {
                const res = await (row.hasOwnProperty('categoryId') ? deleteItemApi(row.id) : deleteCategoryApi(row.id))
                if(res.success) {
                    getList()
                    message.success(i18n.t('deleteSuccess'))
                }else {
                    message.error(res.msg)
                }
            }
            
        },
    ])


    const formCategoryFields:FormField[] = [
        {label : 'id', name : 'id', hidden : true},
        {label : i18n.t('name'), name : 'name', maxlength : 30, required : true},
        {label : i18n.t('code'), name : 'code', maxlength : 20, required : true},
    ]

    const formItemFields:FormField[] = [
        {label : 'id', name : 'id', hidden : true},
        {label : i18n.t('category'), name : 'categoryId', required : true, hidden : true},
        {label : i18n.concat('parent', 'category'), name : 'parentId', hidden : true},
        {label : i18n.t('name'), name : 'name', maxlength : 30, required : true},
        {label : i18n.t('code'), name : 'code', maxlength : 20, required : true},
    ]

    
    const dataRows = computed(() => {
        let rows:any[] = [...categorys.value]
        rows.forEach(row => {
            row.children = []
            for(let i = 0; i < items.value.length; i ++) {
                if(items.value[i].categoryId == row.id) {
                    row.children.push(items.value[i])
                }
            }
        })

        return rows
    })

    function openAddCategory() {
        action.value = 'category'
        dialogTitle.value = i18n.t('add')
        formCategoryFields.forEach(field => {
            if(field.name == 'code') {
                field.defaultValue = generateCodeFromUid()
            }else {
                delete field.defaultValue
            }
            
        })



        visible.value = true

    }

    function openItemAdd(parent) {
        action.value = 'item'
        dialogTitle.value = i18n.t('add')
        formItemFields.forEach(field => {
            delete field.defaultValue
            if(parent.hasOwnProperty('categoryId')) {
                if(field.name == 'categoryId') {
                    field.hidden = true
                    field.defaultValue = parent.categoryId
                }else if(field.name == 'parentId') {
                    field.defaultValue = parent.id
                }
            }else {
                if(field.name == 'categoryId') {
                    field.defaultValue = parent.id
                }else if(field.name == 'parentId') {
                    field.defaultValue = 0
                }
            }

            if(field.name == 'code') {
                field.defaultValue = generateCodeFromUid()
            }
            
        })


        visible.value = true
    }

    function getList() {
        listApi().then(({data}) => {
            categorys.value = data.categorys
            if(data.items.length > 0) {
                items.value = recursionFn(data.items, Math.min(...data.items.map(row => row.parentId)), 'id', 'parentId', 'children')
            }
        })
    }

    async function submit(){
        const formData = await formRef.value.validate()
        const res = await (action.value === 'category' ? saveCategoryApi(formData) : saveItemApi(formData))
        if(res.success) {
            getList()
            visible.value = false
            message.success(i18n.t('saveSuccess'))
        }else {
            Modal.error({
                title : res.msg
            })
        }
    }

    getList()
</script>

<style lang='scss' module>
    .cateogryItem{
        display: flex;
        align-items: center;
        justify-content: space-between;
    }
</style>